package com.xiaoxin.experience.system;

import com.xiaoxin.experience.util.StringUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.web.server.WebServerFactory;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.core.env.*;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Properties;

/**
 * @author xiaoxin
 */
@Component
public class BeanMonitor implements BeanPostProcessor {

    @Resource
    AbstractEnvironment environment;

    @Value("${all.network.listen}")
    boolean allNetworkListen;

    private volatile boolean load = true;

    private static final Object lock = new Object();

    private static final String REGEX = "^encrypt:\\{.*}$";

    @Override
    @Nullable
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
    {
        load();
        return bean;
    }

    private void load()
    {
        if (load)
        {
            synchronized (lock)
            {
                if (load)
                {
                    load = false;
                    MutablePropertySources propertySources = environment.getPropertySources();
                    Properties properties = new Properties();
                    for (PropertySource<?> propertySource : propertySources)
                    {
                        if (propertySource instanceof EnumerablePropertySource)
                        {
                            final String[] propertyNames = ((EnumerablePropertySource<?>) propertySource).getPropertyNames();
                            for (String propertyName : propertyNames)
                            {
                                String property = environment.getProperty(propertyName);
                                decrypt(property,propertyName,properties);
                            }
                        }
                    }
                    propertySources.addFirst(new PropertiesPropertySource("xiaoxin",properties));
                }
            }
        }
    }

    private boolean needDecrypt(String propertyName)
    {
        if (StringUtil.isBlank(propertyName))
        {
            return false;
        }
        return propertyName.matches(REGEX);
    }

    private void decrypt(String property, String propertyName, Properties properties)
    {
        if(needDecrypt(property))
        {
            String encrypt = property.substring(9, property.length() - 1);
            if (StringUtil.isNotBlank(encrypt))
            {
                properties.setProperty(propertyName,DASASEEncryptUtil.decrypt(encrypt));
            }
        }
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException
    {
        if (bean instanceof WebServerFactory && allNetworkListen)
        {
            if (bean instanceof ConfigurableServletWebServerFactory)
            {
                ConfigurableServletWebServerFactory webServerFactory = (ConfigurableServletWebServerFactory)bean;
                webServerFactory.setAddress(null);
            }
        }
        return bean;
    }
}
